package cn.topcodes.tcsf.admin.commons.query;

import cn.topcode.unicorn.utils.DynamicQueryUtil;
import cn.topcodes.tcsf.admin.commons.domain.IdEntity;
import cn.topcodes.tcsf.admin.commons.domain.Page;
import cn.topcodes.tcsf.admin.commons.domain.ValueRangeConstant.DataState;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.entity.Example.Criteria;

import javax.persistence.EntityNotFoundException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Transactional(readOnly = true)
public abstract class QueryIdEntityService<T extends IdEntity>
        extends QueryService<T> implements IQueryIdEntityService<T> {

    @Override
    public T findOneMarkDelete(Long id) {
        Assert.notNull(id);
        T entity = this.findOne(id);
        if (entity != null && DataState.DATA_STATE_DELETE.equals(entity.getDataState())) {
            return entity;
        }
        return null;
    }

    @Override
    public T findOneDisable(Long id) {
        Assert.notNull(id);
        T entity = this.findOne(id);
        if (entity != null && DataState.DATA_STATE_DISABLE.equals(entity.getDataState())) {
            return entity;
        }
        return null;
    }

    @Override
    public T findOneEnable(Long id) {
        Assert.notNull(id);
        T entity = this.findOne(id);
        if (entity != null && DataState.DATA_STATE_ENABLE.equals(entity.getDataState())) {
            return entity;
        }
        return null;
    }

    @Override
    public T findOneMarkDelete(Example example) {
        Assert.notNull(example);
        T entity = this.findOne(example);
        if (entity != null && DataState.DATA_STATE_DELETE.equals(entity.getDataState())) {
            return entity;
        }
        return null;
    }

    @Override
    public T findOneDisable(Example example) {
        Assert.notNull(example);
        T entity = this.findOne(example);
        if (entity != null && DataState.DATA_STATE_DISABLE.equals(entity.getDataState())) {
            return entity;
        }
        return null;
    }

    @Override
    public T findOneEnable(Example example) {
        Assert.notNull(example);
        T entity = this.findOne(example);
        if (entity != null && DataState.DATA_STATE_ENABLE.equals(entity.getDataState())) {
            return entity;
        }
        return null;
    }

    @Override
    public List<T> findAllMarkDelete() {
        Example example = this.buildExample();
        appendAndDataState2Criteria(example, DataState.DATA_STATE_DELETE);
        return this.findAll(example);
    }

    @Override
    public List<T> findAllDisable() {
        Example example = this.buildExample();
        appendAndDataState2Criteria(example, DataState.DATA_STATE_DISABLE);
        return this.findAll(example);
    }

    @Override
    public List<T> findAllEnable() {
        Example example = this.buildExample();
        appendAndDataState2Criteria(example, DataState.DATA_STATE_ENABLE);
        return this.findAll(example);
    }

    @Override
    public List<T> findAllMarkDelete(Example example) {
        example = example == null ? this.buildExample() : example;
        appendAndDataState2Criteria(example, DataState.DATA_STATE_DELETE);
        return this.findAll(example);
    }

    @Override
    public List<T> findAllDisable(Example example) {
        example = example == null ? this.buildExample() : example;
        appendAndDataState2Criteria(example, DataState.DATA_STATE_DISABLE);
        return this.findAll(example);
    }

    @Override
    public List<T> findAllEnable(Example example) {
        example = example == null ? this.buildExample() : example;
        appendAndDataState2Criteria(example, DataState.DATA_STATE_ENABLE);
        return this.findAll(example);
    }

    @Override
    public List<T> findAllMarkDelete(Map<String, String[]> searchParams) {
        searchParams = searchParams == null ? new HashMap<String, String[]>() : searchParams;
        Example example = this.buildExample();
        DynamicQueryUtil.convert(searchParams, example);
        appendAndDataState2Criteria(example, DataState.DATA_STATE_DELETE);
        return this.findAll(example);
    }

    @Override
    public List<T> findAllDisable(Map<String, String[]> searchParams) {
        searchParams = searchParams == null ? new HashMap<String, String[]>() : searchParams;
        Example example = this.buildExample();
        DynamicQueryUtil.convert(searchParams, example);
        appendAndDataState2Criteria(example, DataState.DATA_STATE_DISABLE);
        return this.findAll(example);
    }

    @Override
    public List<T> findAllEnable(Map<String, String[]> searchParams) {
        searchParams = searchParams == null ? new HashMap<String, String[]>() : searchParams;
        Example example = this.buildExample();
        DynamicQueryUtil.convert(searchParams, example);
        appendAndDataState2Criteria(example, DataState.DATA_STATE_ENABLE);
        return this.findAll(example);
    }

    @Override
    public Page<T> findPageMarkDelete(Example example, int pageNumber, int pageSize) {
        example = example == null ? this.buildExample() : example;
        pageNumber = pageNumber < 1 ? 1 : pageNumber;
        pageSize = pageSize < 1 ? 1 : pageSize;
        appendAndDataState2Criteria(example, DataState.DATA_STATE_DELETE);
        return this.findPage(example, pageNumber, pageSize);
    }

    @Override
    public Page<T> findPageDisable(Example example, int pageNumber, int pageSize) {
        example = example == null ? this.buildExample() : example;
        pageNumber = pageNumber < 1 ? 1 : pageNumber;
        pageSize = pageSize < 1 ? 1 : pageSize;
        appendAndDataState2Criteria(example, DataState.DATA_STATE_DISABLE);
        return this.findPage(example, pageNumber, pageSize);
    }

    @Override
    public Page<T> findPageEnable(Example example, int pageNumber, int pageSize) {
        example = example == null ? this.buildExample() : example;
        pageNumber = pageNumber < 1 ? 1 : pageNumber;
        pageSize = pageSize < 1 ? 1 : pageSize;
        appendAndDataState2Criteria(example, DataState.DATA_STATE_ENABLE);
        return this.findPage(example, pageNumber, pageSize);
    }

    @Override
    public Page<T> findPageMarkDelete(Map<String, String[]> searchParams, int pageNumber, int pageSize) {
        searchParams = searchParams == null ? new HashMap<String, String[]>() : searchParams;
        pageNumber = pageNumber < 1 ? 1 : pageNumber;
        pageSize = pageSize < 1 ? 1 : pageSize;
        Example example = this.buildExample();
        DynamicQueryUtil.convert(searchParams, example);
        appendAndDataState2Criteria(example, DataState.DATA_STATE_DELETE);
        return this.findPage(example, pageNumber, pageSize);
    }

    @Override
    public Page<T> findPageDisable(Map<String, String[]> searchParams, int pageNumber, int pageSize) {
        searchParams = searchParams == null ? new HashMap<String, String[]>() : searchParams;
        pageNumber = pageNumber < 1 ? 1 : pageNumber;
        pageSize = pageSize < 1 ? 1 : pageSize;
        Example example = this.buildExample();
        DynamicQueryUtil.convert(searchParams, example);
        appendAndDataState2Criteria(example, DataState.DATA_STATE_DISABLE);
        return this.findPage(example, pageNumber, pageSize);
    }

    @Override
    public Page<T> findPageEnable(Map<String, String[]> searchParams, int pageNumber, int pageSize) {
        searchParams = searchParams == null ? new HashMap<String, String[]>() : searchParams;
        pageNumber = pageNumber < 1 ? 1 : pageNumber;
        pageSize = pageSize < 1 ? 1 : pageSize;
        Example example = this.buildExample();
        DynamicQueryUtil.convert(searchParams, example);
        appendAndDataState2Criteria(example, DataState.DATA_STATE_ENABLE);
        return this.findPage(example, pageNumber, pageSize);
    }

    @Override
    public int countAllMarkDelete() {
        Example example = this.buildExample();
        appendAndDataState2Criteria(example, DataState.DATA_STATE_DELETE);
        return this.getMapper().selectCountByExample(example);
    }

    @Override
    public int countAllDisable() {
        Example example = this.buildExample();
        appendAndDataState2Criteria(example, DataState.DATA_STATE_DISABLE);
        return this.getMapper().selectCountByExample(example);
    }

    @Override
    public int countAllEnable() {
        Example example = this.buildExample();
        appendAndDataState2Criteria(example, DataState.DATA_STATE_ENABLE);
        return this.getMapper().selectCountByExample(example);
    }

    @Override
    public int countMarkDelete(Example example) {
        example = example == null ? this.buildExample() : example;
        appendAndDataState2Criteria(example, DataState.DATA_STATE_DELETE);
        return this.getMapper().selectCountByExample(example);
    }

    @Override
    public int countDisable(Example example) {
        example = example == null ? this.buildExample() : example;
        appendAndDataState2Criteria(example, DataState.DATA_STATE_DISABLE);
        return this.getMapper().selectCountByExample(example);
    }

    @Override
    public int countEnable(Example example) {
        example = example == null ? this.buildExample() : example;
        appendAndDataState2Criteria(example, DataState.DATA_STATE_ENABLE);
        return this.getMapper().selectCountByExample(example);
    }

    private void appendAndDataState2Criteria(Example example, String dataState) {
        Assert.notNull(example);
        Assert.hasText(dataState);
        List<Criteria> criterias = example.getOredCriteria();
        if (criterias.size() == 0) example.createCriteria();
        for (Criteria criteria : criterias) {
            criteria.andEqualTo("dataState", dataState);
        }
    }

    @Override
    public T findOneMarkDeleteOrFail(Example example) {
        T t = this.findOneMarkDelete(example);
        if(t == null) {
            throw new EntityNotFoundException("资源不存在");
        }
        return t;
    }

    @Override
    public T findOneDisableOrFail(Example example) {
        T t = this.findOneDisable(example);
        if(t == null) {
            throw new EntityNotFoundException("资源不存在");
        }
        return t;
    }

    @Override
    public T findOneEnableOrFail(Example example) {
        T t = this.findOneEnable(example);
        if(t == null) {
            throw new EntityNotFoundException("资源不存在");
        }
        return t;
    }

    @Override
    public T findOneMarkDeleteOrFail(Long id) {
        T t = this.findOneMarkDelete(id);
        if(t == null) {
            throw new EntityNotFoundException("资源不存在");
        }
        return t;
    }

    @Override
    public T findOneDisableOrFail(Long id) {
        T t = this.findOneDisable(id);
        if(t == null) {
            throw new EntityNotFoundException("资源不存在");
        }
        return t;
    }

    @Override
    public T findOneEnableOrFail(Long id) {
        T t = this.findOneEnable(id);
        if(t == null) {
            throw new EntityNotFoundException("资源不存在");
        }
        return t;
    }
}
